package org.jsola.hr.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import jdk.nashorn.internal.runtime.ParserException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.jsola.common.CollectionKit;
import org.jsola.common.SafeKit;
import org.jsola.common.StrKit;
import org.jsola.contract.core.MockMultipartFile;
import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.ExcelKit;
import org.jsola.hr.common.RegUtils;
import org.jsola.hr.common.oneKeyPay.AliGetUserInfo;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.constant.TransferAccountsPayStatusEnum;
import org.jsola.hr.constant.TransferAccountsSubjectStatusEnum;
import org.jsola.hr.constant.TransferAccountsTypeEnum;
import org.jsola.hr.dao.ITransferAccountsDetailDAO;
import org.jsola.hr.dto.TransferAccountsDetailAddDTO;
import org.jsola.hr.dto.TransferAccountsDetailUpdateDTO;
import org.jsola.hr.dto.TransferAccountsPeopleAddDTO;
import org.jsola.hr.dto.excel.TransferAccountsDetailImportDTO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.entity.TransferAccountsBatchDO;
import org.jsola.hr.entity.TransferAccountsDetailDO;
import org.jsola.hr.entity.TransferAccountsPeopleDO;
import org.jsola.hr.provider.IFileProviderService;
import org.jsola.hr.provider.IUserProviderService;
import org.jsola.hr.query.TransferAccountsDetailQuery;
import org.jsola.hr.query.TransferBuildDetailQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.service.excel.TransferAccountsDetailListener;
import org.jsola.hr.vo.*;
import org.jsola.hr.vo.payWx.VxWgkUserAuthResultVO;
import org.jsola.user.core.TokenUser;
import org.jsola.user.entity.UserDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 转账明细
 *
 * @author zhr
 */
@Slf4j
@Service("hrTransferAccountsDetailServiceImpl")
public class TransferAccountsDetailServiceImpl implements ITransferAccountsDetailService {

    @Autowired
    private ITransferAccountsDetailDAO transferAccountsDetailDAO;
    @Autowired
    private ITransferAccountsBatchService transferAccountsBatchService;
    @Autowired
    private ITransferAccountsPeopleService transferAccountsPeopleService;
    @Autowired
    private ITransferAccountInfoService transferAccountInfoService;

    @Autowired
    private IEmpInfoService empInfoService;
    @Autowired
    private IUserProviderService userProviderService;
    @Autowired
    private IFileProviderService fileProviderService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public TransferAccountsDetailVO save(TransferAccountsDetailAddDTO transferAccountsDetailAddDTO, TokenUser tokenUser) {
        // 转DO
        TransferAccountsDetailDO transferAccountsDetailDO = transferAccountsDetailAddDTO.to(TransferAccountsDetailDO.class);
        // 保存
        transferAccountsDetailDO = save(transferAccountsDetailDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return transferAccountsDetailDO.to(TransferAccountsDetailVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int saveBatch(List<TransferAccountsDetailAddDTO> transferAccountsDetailAddDTOList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(transferAccountsDetailAddDTOList)) {
            return 0;
        }
        int count = 0;
        String batchId = transferAccountsDetailAddDTOList.get(0).getBatchId();
        // 查找批次信息
        TransferAccountsBatchDO transferAccountsBatchDO = transferAccountsBatchService.selectDOById(batchId, tokenUser.getSiteId());
        if (transferAccountsBatchDO == null) {
            throw new ParserException("明细对应的批次不存在或已删除，新增失败！");
        }
        BigDecimal money = new BigDecimal("0");
        for (TransferAccountsDetailAddDTO transferAccountsDetailAddDTO : transferAccountsDetailAddDTOList) {
            if (StrKit.isEmpty(transferAccountsDetailAddDTO.getBatchId())) {
                throw new ParserException("批次id不能为空");
            }
            if (StrKit.isEmpty(batchId)) {
                batchId = transferAccountsDetailAddDTO.getBatchId();
            } else {
                if (!batchId.equals(transferAccountsDetailAddDTO.getBatchId())) {
                    throw new ParserException("不允许同时新增不同批次的明细信息!");
                }
            }
            if (transferAccountsDetailAddDTO.getMoney() != null) {
                money = money.add(transferAccountsDetailAddDTO.getMoney());
            }
            transferAccountsDetailAddDTO.setOrderTitle(transferAccountsBatchDO.getOrderTitle());
            this.save(transferAccountsDetailAddDTO, tokenUser);
            count++;
        }
        transferAccountsBatchDO.setMoney(transferAccountsBatchDO.getMoney().add(money));
        transferAccountsBatchDO.setTotalCount(transferAccountsBatchDO.getTotalCount() + count);
        // 需要修改批次里面的金额 笔数
        transferAccountsBatchService.updateById(transferAccountsBatchDO, tokenUser.getSiteId(),
                tokenUser.getUserId());
        return count;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(TransferAccountsDetailUpdateDTO transferAccountsDetailUpdateDTO, TokenUser tokenUser) {
        if (transferAccountsDetailUpdateDTO.getMoney() != null) {
            if (transferAccountsDetailUpdateDTO.getMoney().intValue() > 50000) {
                throw new ParamException("单个金额不能超过5w");
            }
            TransferAccountsDetailDO oldTransferAccountsDetailDO = this
                    .selectDOById(transferAccountsDetailUpdateDTO.getId(), tokenUser.getSiteId());
            if (oldTransferAccountsDetailDO == null) {
                throw new ParserException("明细不存在或已删除，请刷新重试！");
            }
            // 查找批次信息
            TransferAccountsBatchDO transferAccountsBatchDO = transferAccountsBatchService
                    .selectDOById(oldTransferAccountsDetailDO.getBatchId(), tokenUser.getSiteId());
            if (transferAccountsBatchDO == null) {
                throw new ParserException("明细对应的批次不存在或已删除，该条明细不能修改！");
            }
            BigDecimal oldMoney = oldTransferAccountsDetailDO.getMoney() == null ?
                    new BigDecimal("0") : oldTransferAccountsDetailDO.getMoney();
            BigDecimal addMoney = transferAccountsDetailUpdateDTO.getMoney().subtract(oldMoney);
            transferAccountsBatchDO.setMoney(transferAccountsBatchDO.getMoney().add(addMoney));
            // 需要修改批次里面的金额
            transferAccountsBatchService.updateById(transferAccountsBatchDO, tokenUser.getSiteId(),
                    tokenUser.getUserId());
        }
        //转DO
        TransferAccountsDetailDO transferAccountsDetailDO = transferAccountsDetailUpdateDTO.to(TransferAccountsDetailDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(transferAccountsDetailDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int updateBatch(TransferAccountsDetailUpdateDTO transferAccountsDetailUpdateDTO, TokenUser tokenUser) {
        if (CollectionKit.isEmpty(transferAccountsDetailUpdateDTO.getIds())) {
            throw new ParamException("修改id不能为空！");
        }
        int count = 0;
        for (String id : transferAccountsDetailUpdateDTO.getIds()) {
            transferAccountsDetailUpdateDTO.setId(id);
            count += this.update(transferAccountsDetailUpdateDTO, tokenUser);
        }
        return count;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... transferAccountsDetailIds) {
        // 删除前需要修改批次的信息
        BigDecimal subMoney = new BigDecimal("0");
        String batchId = "";
        for (String transferAccountsDetailId : transferAccountsDetailIds) {
            TransferAccountsDetailVO transferAccountsDetailVO = this
                    .selectById(transferAccountsDetailId, tokenUser.getSiteId());
            if (transferAccountsDetailVO == null) {
                throw new ParserException("id有误，请刷新重试，或联系管理员! 错误id为：" + transferAccountsDetailId);
            }
            if (StrKit.isEmpty(batchId)) {
                batchId = transferAccountsDetailVO.getBatchId();
            } else {
                if (!batchId.equals(transferAccountsDetailVO.getBatchId())) {
                    throw new ParserException("不允许同时删除不同批次的明细信息!");
                }
            }
            if (transferAccountsDetailVO.getMoney() != null) {
                subMoney = subMoney.add(transferAccountsDetailVO.getMoney());
            }
        }
        // 查找批次信息
        TransferAccountsBatchDO transferAccountsBatchDO = transferAccountsBatchService.selectDOById(batchId, tokenUser.getSiteId());
        if (transferAccountsBatchDO == null) {
            throw new ParserException("明细对应的批次不存在或已删除，明细不能删除！");
        }
        transferAccountsBatchDO.setMoney(transferAccountsBatchDO.getMoney().subtract(subMoney));
        transferAccountsBatchDO.setTotalCount(transferAccountsBatchDO.getTotalCount() - transferAccountsDetailIds.length);
        // 需要修改批次里面的金额 笔数
        transferAccountsBatchService.updateById(transferAccountsBatchDO, tokenUser.getSiteId(),
                tokenUser.getUserId());

        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) transferAccountsDetailIds);
    }


    @Override
    public TransferAccountsDetailVO selectById(String transferAccountsDetailId, String siteId) {
        TransferAccountsDetailDO transferAccountsDetailDO = selectDOById(transferAccountsDetailId, siteId);
        if (transferAccountsDetailDO == null) {
            return null;
        }
        return transferAccountsDetailDO.to(TransferAccountsDetailVO.class);
    }

    @Override
    public List<TransferAccountsDetailListVO> select(TransferAccountsDetailQuery transferAccountsDetailQuery, String siteId) {
        List<TransferAccountsDetailDO> transferAccountsDetailDOList = selectDO(transferAccountsDetailQuery, siteId);
        if(CollectionUtils.isEmpty(transferAccountsDetailDOList)) {
            return transferAccountsDetailDOList == null ? null : new ArrayList<>();
        }
        return transferAccountsDetailDOList.stream()
                .map(transferAccountsDetailDO -> transferAccountsDetailDO.to(TransferAccountsDetailListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(TransferAccountsDetailQuery transferAccountsDetailQuery, String siteId) {
        Example example = buildExample(transferAccountsDetailQuery,siteId);
        return transferAccountsDetailDAO.selectCountByExample(example);
    }

    @Override
    public Page<TransferAccountsDetailListVO> selectPage(TransferAccountsDetailQuery transferAccountsDetailQuery, String siteId) {
        ParamException.hasText(transferAccountsDetailQuery.getBatchId(), "转账批次id不能为空");
        Example example = buildExample(transferAccountsDetailQuery,siteId);
        Page<TransferAccountsDetailDO> page = transferAccountsDetailDAO.selectPageByExample(example,
                transferAccountsDetailQuery.getPageNo(),
                transferAccountsDetailQuery.getPageSize());

        return page.to(TransferAccountsDetailListVO.class);
    }

    @Override
    public TransferAccountsDetailDO selectDOById(String transferAccountsDetailId, String siteId) {
        return listById(transferAccountsDetailId, siteId);
    }

    @Override
    public List<TransferAccountsDetailDO> selectDO(TransferAccountsDetailQuery transferAccountsDetailQuery, String siteId) {
        Example example = buildExample(transferAccountsDetailQuery,siteId);
        return transferAccountsDetailDAO.selectByExample(example);
    }

    @Override
    public List<TransferAccountsDetailDO> selectByBatchId(String batchId, String siteId) {
        if (StrKit.isEmpty(batchId) || StrKit.isEmpty(siteId)) {
            return new ArrayList<>();
        }
        Example example = new Example(TransferAccountsDetailDO.class);
        example.and()
                .andEqualTo("batchId", batchId)
                .andEqualTo("siteId", siteId)
                .andEqualTo("valid", true);
        return transferAccountsDetailDAO.selectByExample(example);
    }

    @Override
    public List<String> selectIdsByBatchId(TransferAccountsDetailQuery transferAccountsDetailQuery, String siteId) {
        Example example = buildExample(transferAccountsDetailQuery,siteId);
        List<TransferAccountsDetailDO> transferAccountsDetailDOList = transferAccountsDetailDAO.selectByExample(example);
        List<String> detailIdList = new ArrayList<>();
        if (CollectionUtils.isEmpty(transferAccountsDetailDOList)) {
            return detailIdList;
        }
        detailIdList = transferAccountsDetailDOList.stream().map(TransferAccountsDetailDO::getId).collect(Collectors.toList());
        return detailIdList;
    }

    @Override
    public TransferAccountsDetailDO selectByBatchIdAndIdCard(String batchId, String idCard, String siteId) {
        if (StrKit.isEmpty(batchId) || StrKit.isEmpty(idCard) || StrKit.isEmpty(siteId)) {
            return null;
        }
        Example example = new Example(TransferAccountsDetailDO.class);
        example.and()
                .andEqualTo("batchId", batchId)
                .andEqualTo("idCard", idCard)
                .andEqualTo("siteId", siteId)
                .andEqualTo("valid", true);
        return transferAccountsDetailDAO.selectOneByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public TransferAccountsDetailImportAllVO buildDetailAddDTOList(TransferBuildDetailQuery transferBuildDetailQuery,
                                                                    TokenUser tokenUser) {
        TransferAccountsDetailImportAllVO transferAccountsDetailImportAllVO = new TransferAccountsDetailImportAllVO();
        // 构造返回的数据
        Integer type = transferBuildDetailQuery.getType();
        String batchId = transferBuildDetailQuery.getBatchId();
        List<TransferBuildDetailAddVO> transferBuildDetailAddVOList = transferBuildDetailQuery
                .getTransferBuildDetailAddVOList();
        if (transferBuildDetailAddVOList == null) {
            transferBuildDetailAddVOList = new ArrayList<>();
        }
        ParamException.notNull(type, "到账类型不能为空!");
        // 如果批次id不为空 需要校验身份证是否重复
        List<TransferAccountsDetailDO> transferAccountsDetailDOList = this.selectByBatchId(batchId, tokenUser.getSiteId());
        List<String> existIdCards = transferAccountsDetailDOList.stream().map(TransferAccountsDetailDO::getIdCard)
                .collect(Collectors.toList());
        List<String> existPhones = transferAccountsDetailDOList.stream().map(TransferAccountsDetailDO::getPhone)
                .collect(Collectors.toList());
        List<String> existIdentitys = transferAccountsDetailDOList.stream().map(TransferAccountsDetailDO::getIdentity)
                .collect(Collectors.toList());
        // 批次已有人数
        int yetNumber = transferAccountsDetailDOList.size();
        // 失败的数据
        List<TransferAccountsDetailAddDTO> failTransferAccountsDetailAddDTOList = new ArrayList<>();
        // 成功的数据
        List<TransferAccountsDetailAddDTO> successTransferAccountsDetailAddDTOList = new ArrayList<>();
        Map<String, String> idCardMap = new HashMap<>(8);
        Map<String, String> phoneMap = new HashMap<>(8);
        Map<String, String> identityMap = new HashMap<>(8);
        for (TransferBuildDetailAddVO transferBuildDetailAddVO : transferBuildDetailAddVOList) {
            foundTransferAccountsDetail(transferBuildDetailAddVO, type, batchId, tokenUser,
                    failTransferAccountsDetailAddDTOList, successTransferAccountsDetailAddDTOList,
                    idCardMap, phoneMap, identityMap, existIdCards, existPhones, existIdentitys);
        }
        if (yetNumber + successTransferAccountsDetailAddDTOList.size() > 500) {
            throw new ParamException("一个批次不能超过500人");
        }
        transferAccountsDetailImportAllVO.setSuccessTransferAccountsDetailAddDTOList(successTransferAccountsDetailAddDTOList);
        transferAccountsDetailImportAllVO.setFailTransferAccountsDetailAddDTOList(failTransferAccountsDetailAddDTOList);
        return transferAccountsDetailImportAllVO;
    }

    private void foundTransferAccountsDetail(TransferBuildDetailAddVO transferBuildDetailAddVO,
                                             Integer type, String batchId, TokenUser tokenUser,
                                             List<TransferAccountsDetailAddDTO> failTransferAccountsDetailAddDTOList,
                                             List<TransferAccountsDetailAddDTO> successTransferAccountsDetailAddDTOList,
                                             Map<String, String> idCardMap,
                                             Map<String, String> phoneMap,
                                             Map<String, String> identityMap,
                                             List<String> existIdCards,
                                             List<String> existPhones,
                                             List<String> existIdentitys) {
        String id = transferBuildDetailAddVO.getId();
        if (StrKit.isEmpty(id) || transferBuildDetailAddVO.getType() == null) {
            throw new ParserException("transferBuildDetailAddVO参数都不能为空!");
        }
        String failField;
        if (type.equals(TransferAccountsTypeEnum.ZFB.getValue())) {
            failField = "支付宝号";
        } else if (type.equals(TransferAccountsTypeEnum.VX.getValue())) {
            failField = "姓名";
        } else {
            failField = "银行卡号";
        }
        TransferAccountsDetailAddDTO transferAccountsDetailAddDTO = new TransferAccountsDetailAddDTO();
        transferAccountsDetailAddDTO.setType(type);
        transferAccountsDetailAddDTO.setBatchId(batchId);
        transferAccountsDetailAddDTO.setPayStatus(TransferAccountsPayStatusEnum.NO_PAY.getValue());
        transferAccountsDetailAddDTO.setSubjectStatus(TransferAccountsSubjectStatusEnum.WAIT_APPLICATION.getValue());
        TransferAccountsPeopleVO transferAccountsPeopleVO;
        if (transferBuildDetailAddVO.getType() != 1) {
            // 从花名册查询
            EmpInfoDO empInfoDO = empInfoService.selectDOById(id, tokenUser.getSiteId());
            ParamException.notNull(empInfoDO, "花名册ID不正确，请刷新重试");
            // 校验身份证
            String idCard = empInfoDO.getIdCard();
            transferAccountsDetailAddDTO.setName(empInfoDO.getName());
            transferAccountsDetailAddDTO.setIdCard(idCard);
            transferAccountsDetailAddDTO.setPhone(empInfoDO.getPhone());
            if (StrKit.isEmpty(idCard)) {
                transferAccountsDetailAddDTO.setFailField("身份证号");
                transferAccountsDetailAddDTO.setImportFailReason("花名册身份证信息为空!");
                failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
                return;
            }
            if (!RegUtils.isIdCard(idCard)) {
                transferAccountsDetailAddDTO.setFailField("身份证号");
                transferAccountsDetailAddDTO.setImportFailReason("身份证号格式不对");
                failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
                return;
            }
            if (!RegUtils.isBankCard(empInfoDO.getBankCard())) {
                empInfoDO.setBankCard(null);
                empInfoDO.setBankName("");
            } else {
                // 识别开户行
                if (StrKit.isEmpty(empInfoDO.getBankName())) {
                    String bankName = AliGetUserInfo.bankNameByBankNo(empInfoDO.getBankCard());
                    bankName = AliGetUserInfo.bankNameToChinese(bankName);
                    empInfoDO.setBankName(bankName);
                }
            }
            // 根据idCard查询人员库
            TransferAccountsPeopleDO transferAccountsPeopleDO = transferAccountsPeopleService
                    .selectByIdCard(idCard, tokenUser.getSiteId());
            String openId = userProviderService.selectOpenIdByUserId(empInfoDO.getUserId(), tokenUser);
            // 查询微工卡授权状态
            boolean sisVxBinding = false;
            if (StrKit.isNotEmpty(openId)) {
                VxWgkUserAuthResultVO vxWgkUserAuthResultVO = transferAccountInfoService.selectUserAuthStatus(openId,
                        tokenUser.getSiteId());
                if (vxWgkUserAuthResultVO != null &&
                        "AUTHORIZED".equals(vxWgkUserAuthResultVO.getAuthorizeState())) {
                    sisVxBinding = true;
                }
            }
            if (transferAccountsPeopleDO != null) {
                String error = transferAccountsPeopleService.checkUpdate(transferAccountsPeopleDO, empInfoDO.getName(),
                        empInfoDO.getPhone(), empInfoDO.getAlipayAccount(), empInfoDO.getBankCard(), empInfoDO.getBankName());
                if (StrKit.isNotEmpty(error)) {
                    transferAccountsDetailAddDTO.setFailField(failField);
                    transferAccountsDetailAddDTO.setImportFailReason(error);
                    failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
                    return;
                }
                // 修改人员库信息
                transferAccountsPeopleDO.setZfbIdentity(empInfoDO.getAlipayAccount());
                transferAccountsPeopleDO.setBankIdentity(empInfoDO.getBankCard());
                transferAccountsPeopleDO.setOpeningBank(empInfoDO.getBankName());
                transferAccountsPeopleDO.setPhone(empInfoDO.getPhone());
                transferAccountsPeopleDO.setVxIdentity(openId);
                transferAccountsPeopleDO.setIsVxBinding(sisVxBinding);
                transferAccountsPeopleService.updateByIdSelective(transferAccountsPeopleDO);
                transferAccountsPeopleVO = transferAccountsPeopleDO.to(TransferAccountsPeopleVO.class);
            } else {
                // 新增人员库信息
                TransferAccountsPeopleAddDTO transferAccountsPeopleAddDTO = new TransferAccountsPeopleAddDTO();
                transferAccountsPeopleAddDTO.setCompanyId(empInfoDO.getCompanyId());
                transferAccountsPeopleAddDTO.setPhone(empInfoDO.getPhone());
                UserDO userDO = userProviderService.selectUserById(empInfoDO.getUserId());
                if (userDO != null) {
                    transferAccountsPeopleAddDTO.setAvatar(userDO.getAvatar());
                }
                transferAccountsPeopleAddDTO.setName(empInfoDO.getName());
                transferAccountsPeopleAddDTO.setIdCard(empInfoDO.getIdCard());
                transferAccountsPeopleAddDTO.setOpeningBank(empInfoDO.getBankName());
                transferAccountsPeopleAddDTO.setVxIdentity(openId);
                transferAccountsPeopleAddDTO.setIsVxBinding(sisVxBinding);
                transferAccountsPeopleAddDTO.setZfbIdentity(empInfoDO.getAlipayAccount());
                transferAccountsPeopleAddDTO.setBankIdentity(empInfoDO.getBankCard());
                transferAccountsPeopleVO = transferAccountsPeopleService
                        .save(transferAccountsPeopleAddDTO, tokenUser);
            }
        } else {
            // 从人员库查询
            TransferAccountsPeopleDO transferAccountsPeopleDO = transferAccountsPeopleService
                    .selectDOById(id, tokenUser.getSiteId());
            ParamException.notNull(transferAccountsPeopleDO, "人员库ID不正确，请刷新重试");
            transferAccountsPeopleVO = transferAccountsPeopleDO.to(TransferAccountsPeopleVO.class);
        }
        // 设置返回值
        transferAccountsDetailAddDTO.setPhone(transferAccountsPeopleVO.getPhone());
        transferAccountsDetailAddDTO.setCompanyId(transferAccountsPeopleVO.getCompanyId());
        transferAccountsDetailAddDTO.setPeopleId(transferAccountsPeopleVO.getId());
        transferAccountsDetailAddDTO.setName(transferAccountsPeopleVO.getName());
        transferAccountsDetailAddDTO.setIdCard(transferAccountsPeopleVO.getIdCard());
        transferAccountsDetailAddDTO.setBankId(transferAccountsPeopleVO.getBankIdentity());
        if (TransferAccountsTypeEnum.ZFB.getValue().equals(type)) {
            if (StrKit.isEmpty(transferAccountsPeopleVO.getZfbIdentity())) {
                transferAccountsDetailAddDTO.setFailField(failField);
                transferAccountsDetailAddDTO.setImportFailReason("支付宝账号不能为空!");
                failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
                return;
            }
            transferAccountsDetailAddDTO.setIdentity(transferAccountsPeopleVO.getZfbIdentity());
        } else if (TransferAccountsTypeEnum.VX.getValue().equals(type)) {
            transferAccountsDetailAddDTO.setIdentity(transferAccountsPeopleVO.getVxIdentity());
            transferAccountsDetailAddDTO.setIdentityBinding(transferAccountsPeopleVO.getIsVxBinding());
        } else if (TransferAccountsTypeEnum.BANK.getValue().equals(type)) {
            if (StrKit.isEmpty(transferAccountsPeopleVO.getBankIdentity())) {
                transferAccountsDetailAddDTO.setFailField(failField);
                transferAccountsDetailAddDTO.setImportFailReason("银行卡号不能为空!");
                failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
                return;
            }
            transferAccountsDetailAddDTO.setIdentity(transferAccountsPeopleVO.getBankIdentity());
            String bankName = transferAccountsPeopleVO.getOpeningBank();
            if (StrKit.isEmpty(bankName)) {
                bankName = AliGetUserInfo.bankNameByBankNo(transferAccountsPeopleVO.getBankIdentity());
                bankName = AliGetUserInfo.bankNameToChinese(bankName);
            }
            transferAccountsDetailAddDTO.setIsPingAnBank(bankName.contains("平安银行"));
            transferAccountsDetailAddDTO.setBankName(bankName);
        }
        if (StrKit.isNotEmpty(transferAccountsPeopleVO.getPhone())
                && existPhones.contains(transferAccountsPeopleVO.getPhone())) {
            transferAccountsDetailAddDTO.setFailField("手机号");
            transferAccountsDetailAddDTO.setImportFailReason("手机号在批次明细中已存在!");
            failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
            return;
        }
        if (phoneMap.containsKey(transferAccountsPeopleVO.getPhone())) {
            transferAccountsDetailAddDTO.setFailField("手机号");
            transferAccountsDetailAddDTO.setImportFailReason("手机号重复!");
            failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
            return;
        }
        if (StrKit.isNotEmpty(transferAccountsDetailAddDTO.getIdentity())
                && existIdentitys.contains(transferAccountsDetailAddDTO.getIdentity())) {
            transferAccountsDetailAddDTO.setFailField(failField);
            transferAccountsDetailAddDTO.setImportFailReason("转账账号在批次明细中已存在!");
            failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
            return;
        }
        if (identityMap.containsKey(transferAccountsDetailAddDTO.getIdentity())) {
            transferAccountsDetailAddDTO.setFailField(failField);
            transferAccountsDetailAddDTO.setImportFailReason("转账账号重复!");
            failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
            return;
        }
        if (existIdCards.contains(transferAccountsPeopleVO.getIdCard())) {
            transferAccountsDetailAddDTO.setFailField("身份证号");
            transferAccountsDetailAddDTO.setImportFailReason("身份证信息在批次明细中已存在!");
            failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
            return;
        }
        if (idCardMap.containsKey(transferAccountsPeopleVO.getIdCard())) {
            transferAccountsDetailAddDTO.setFailField("身份证号");
            transferAccountsDetailAddDTO.setImportFailReason("身份证信息重复!");
            failTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
            return;
        }
        if (StrKit.isNotEmpty(transferAccountsPeopleVO.getPhone())) {
            phoneMap.put(transferAccountsPeopleVO.getPhone(), transferAccountsPeopleVO.getPhone());
        }
        if (StrKit.isNotEmpty(transferAccountsDetailAddDTO.getIdentity())) {
            identityMap.put(transferAccountsDetailAddDTO.getIdentity(), transferAccountsDetailAddDTO.getIdentity());
        }
        idCardMap.put(transferAccountsPeopleVO.getIdCard(), transferAccountsDetailAddDTO.getIdCard());
        successTransferAccountsDetailAddDTOList.add(transferAccountsDetailAddDTO);
    }


    @Override
    public String selectExportList(TransferAccountsDetailQuery transferAccountsDetailQuery,
                                   TokenUser tokenUser) {
        ParamException.hasText(transferAccountsDetailQuery.getBatchId(), "转账批次id不能为空");
        List<TransferAccountsDetailListVO> detailListVOS = select(transferAccountsDetailQuery, tokenUser.getSiteId());
        if (CollectionUtils.isEmpty(detailListVOS)) {
            ParamException.notEmpty(detailListVOS, "没有需要导出的数据，请检查检索条件");
        }
        return ExcelKit.writeCustomizeExcelWithModel("转账批次明细", transferAccountsDetailQuery.getExportColumns(),
                detailListVOS, false, null, (CellWriteHandler) null);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public TransferAccountsDetailImportAllVO recognitionDetailInfo(File file, String batchId, String companyId,
                                                                   Integer type, TokenUser tokenUser) {
        if (StrKit.isEmpty(companyId)) {
            throw new ParamException("公司id不能为空!");
        }
        TransferAccountsDetailImportAllVO transferAccountsDetailImportAllVO = new TransferAccountsDetailImportAllVO();
        TransferAccountsDetailListener transferAccountsDetailListener = new TransferAccountsDetailListener(batchId,
                companyId, tokenUser, type);
        transferAccountsDetailListener.setParseOnly(false);
        // 读取excel入库
        EasyExcel.read(file, TransferAccountsDetailImportDTO.class, transferAccountsDetailListener).sheet().doRead();
        // 返回信息
        transferAccountsDetailImportAllVO.setFailTransferAccountsDetailAddDTOList(
                transferAccountsDetailListener.getFailTransferAccountsDetailAddDTOList());
        transferAccountsDetailImportAllVO.setSuccessTransferAccountsDetailAddDTOList(
                transferAccountsDetailListener.getSuccessTransferAccountsDetailAddDTOList());
        TransferAccountsBatchVO transferAccountsBatchVO = new TransferAccountsBatchVO();
        transferAccountsBatchVO.setId(batchId);
        transferAccountsDetailImportAllVO.setTransferAccountsBatchVO(transferAccountsBatchVO);
        return transferAccountsDetailImportAllVO;
    }

    @Override
    public String exportFailTransferAccountsDetail(List<TransferAccountsDetailAddDTO> failTransferAccountsDetailAddDTOList,
                                                   Integer type) {
        // 数据
        List<List<String>> dataList = new ArrayList<>();
        // 表头
        List<List<String>> headList = new ArrayList<>();
        List<String> headArray = new ArrayList<>();
        headArray.add("姓名");
        headArray.add("身份证号");
        headArray.add("手机号");
        if (TransferAccountsTypeEnum.ZFB.getValue().equals(type)) {
            headArray.add("支付宝账号");
        } else if (TransferAccountsTypeEnum.BANK.getValue().equals(type)) {
            headArray.add("银行卡号");
        }
        headArray.add("发放金额");
        headArray.add("异常原因");
        for (String headItem : headArray) {
            List<String> head = new ArrayList<>();
            head.add(headItem);
            headList.add(head);
        }
        for (TransferAccountsDetailAddDTO data : failTransferAccountsDetailAddDTOList) {
            List<String> oneDate = new ArrayList<>();
            oneDate.add(data.getName());
            oneDate.add(data.getIdCard());
            oneDate.add(data.getPhone());
            if (TransferAccountsTypeEnum.ZFB.getValue().equals(type)) {
                oneDate.add(data.getIdentity());
            } else if (TransferAccountsTypeEnum.BANK.getValue().equals(type)) {
                oneDate.add(data.getIdentity());
            }
            oneDate.add(data.getMoney() == null ? "" : data.getMoney().toString());
            oneDate.add(data.getImportFailReason());
            dataList.add(oneDate);
        }
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        headWriteCellStyle.setWrapped(false);
        headWriteCellStyle.setShrinkToFit(true);
        // 单元格策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        contentWriteCellStyle.setWrapped(false);
        return ExcelKit.writeExcelWithModel("异常数据", dataList, headList, false,
                headWriteCellStyle, contentWriteCellStyle,  null, (CellWriteHandler) null);
    }

    @Override
    public String uploadFileNotLoginFailList(List<TransferAccountsDetailAddDTO> failTransferAccountsDetailAddDTOList, Integer type) {
        try {
            String localFilePath = this.exportFailTransferAccountsDetail(failTransferAccountsDetailAddDTOList, type);
            String fileName = localFilePath.substring(localFilePath.lastIndexOf(File.separator) + 1, localFilePath.lastIndexOf("."));
            File file = new File(localFilePath);
            FileInputStream fileInputStreamOne = new FileInputStream(file);
            MultipartFile multipartFile = new MockMultipartFile("copy" + fileName, fileName + ".xlsx",
                    ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStreamOne);
            return fileProviderService.generalUpload(multipartFile, "attachment").get(0);
        } catch (IOException e) {
            log.error("导出失败的错误信息失败，失败原因{}", e.getMessage());
            throw new ParamException("生成文件失败，请稍后重试或联系管理员！");
        }
    }

    @Override
    public TransferAccountsDetailDO selectByThirdPartyId(String thirdPartyId, String siteId) {
        if (StrKit.isEmpty(thirdPartyId) || StrKit.isEmpty(siteId)) {
            throw new ParamException("第三方明细id及租户id都不能为空!");
        }
        Example example = new Example(TransferAccountsDetailDO.class);
        example.and()
                .andEqualTo("thirdpartyDetailId", thirdPartyId)
                .andEqualTo("siteId", siteId)
                .andEqualTo("valid", true);
        List<TransferAccountsDetailDO> transferAccountsDetailDOList = transferAccountsDetailDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(transferAccountsDetailDOList)) {
            return null;
        }
        if (transferAccountsDetailDOList.size() > 1) {
            throw new ParamException("根据第三方明细id查询到不止一条数据，请联系管理员查看原因!");
        }
        return transferAccountsDetailDOList.get(0);
    }

    @Override
    public List<TransferAccountsDetailDO> selectByPeopleIdAndSubjectStatus(String peopleId, Integer subjectStatus, String siteId) {
        if (StrKit.isEmpty(peopleId) || subjectStatus == null || StrKit.isEmpty(siteId)) {
            return new ArrayList<>();
        }
        Example example = new Example(TransferAccountsDetailDO.class);
        example.and()
                .andEqualTo("peopleId", peopleId)
                .andEqualTo("subjectStatus", subjectStatus)
                .andEqualTo("siteId", siteId)
                .andEqualTo("valid", true);
        return transferAccountsDetailDAO.selectByExample(example);
    }

    @Override
    public Page<TransferAccountsDetailListVO> selectPageByPeopleId(TransferAccountsDetailQuery transferAccountsDetailQuery, String siteId) {
        if (StrKit.isEmpty(transferAccountsDetailQuery.getPeopleId()) || StrKit.isEmpty(siteId)) {
            throw new ParamException("转账人员id或siteId都不能为空!");
        }
        Example example = new Example(TransferAccountsDetailDO.class);
        example.and()
                .andEqualTo("peopleId", transferAccountsDetailQuery.getPeopleId())
                .andEqualTo("payStatus", TransferAccountsPayStatusEnum.SUCCESS_PAY.getValue())
                .andEqualTo("siteId", siteId)
                .andEqualTo("valid", true);
        example.orderBy("payTime").desc();
        Page<TransferAccountsDetailDO> page = transferAccountsDetailDAO.selectPageByExample(example,
                transferAccountsDetailQuery.getPageNo(),
                transferAccountsDetailQuery.getPageSize());

        return page.to(TransferAccountsDetailListVO.class);
    }

    @Override
    public String selectExportErrorList(TransferAccountsDetailQuery transferAccountsDetailQuery, TokenUser tokenUser) {
        ParamException.hasText(transferAccountsDetailQuery.getBatchId(), "转账批次id不能为空");
        List<TransferAccountsDetailListVO> detailListVOS = select(transferAccountsDetailQuery, tokenUser.getSiteId());
        if (CollectionUtils.isEmpty(detailListVOS)) {
            ParamException.notEmpty(detailListVOS, "没有需要导出的数据，请检查检索条件");
        }
        // 数据
        List<List<String>> dataList = new ArrayList<>();
        // 表头
        List<List<String>> headList = new ArrayList<>();
        String[] headArray = {"姓名", "身份证号", "手机号", "发放账号", "薪资", "单笔交易流水号", "异常原因", "处理状态", "备注"};
        for (String headItem : headArray) {
            List<String> head = new ArrayList<>();
            head.add(headItem);
            headList.add(head);
        }
        for (TransferAccountsDetailListVO data : detailListVOS) {
            List<String> oneDate = new ArrayList<>();
            oneDate.add(data.getName());
            oneDate.add(data.getIdCard());
            oneDate.add(data.getPhone());
            if (TransferAccountsTypeEnum.VX.getValue().equals(data.getType())) {
                oneDate.add("---");
            } else {
                oneDate.add(data.getIdentity());
            }
            oneDate.add(SafeKit.getString(data.getMoney()));
            oneDate.add(data.getThirdPartyInteriorDetailId());
            oneDate.add(data.getFailCause());
            oneDate.add(data.getIsDispose() == null ?
                    "" : data.getIsDispose() ? "已处理" : "未处理");
            oneDate.add(data.getRemark());
            dataList.add(oneDate);
        }
        return ExcelKit.writeExcelWithModel("转账批次明细", dataList, headList, false, null,
                (CellWriteHandler) null);
    }

    @Override
    public int deleteByBatchId(String batchId, TokenUser tokenUser) {
        List<TransferAccountsDetailDO> transferAccountsDetailDOList = this.selectByBatchId(batchId, tokenUser.getSiteId());
        if (CollectionUtils.isEmpty(transferAccountsDetailDOList)) {
            return 0;
        }
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(),
                transferAccountsDetailDOList.stream().map(TransferAccountsDetailDO::getId).toArray());
    }

    @Override
    public int updateBatchAndBatchInfo(TransferAccountsDetailUpdateDTO transferAccountsDetailUpdateDTO, TokenUser tokenUser) {
        String batchId = transferAccountsDetailUpdateDTO.getBatchId();
        if (StrKit.isEmpty(batchId)) {
            throw new ParamException("批次id不能为空！");
        }
        int count = this.updateBatch(transferAccountsDetailUpdateDTO, tokenUser);
        // 查询该批次的全部未处理的批次明细（修改批次的信息）
        TransferAccountsBatchDO transferAccountsBatchDO = transferAccountsBatchService
                .selectDOById(batchId, tokenUser.getSiteId());
        ParamException.notNull(transferAccountsBatchDO, "批次不存在或已删除，请刷新重试！");
        Example example = new Example(TransferAccountsDetailDO.class);
        example.and()
                .andEqualTo("isDispose", false)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andEqualTo("batchId", batchId);
        int number = transferAccountsDetailDAO.selectCountByExample(example);
        if (number == 0) {
            transferAccountsBatchDO.setIsDispose(true);
        } else {
            transferAccountsBatchDO.setIsDispose(false);
        }
        transferAccountsBatchService.updateByIdSelective(transferAccountsBatchDO);
        return count;
    }


    /**
     * 根据查询参数，构建example

     * @param transferAccountsDetailQuery 查询参数
     * @param siteId 所属站点id
     * @return example
     */
    private Example buildExample(TransferAccountsDetailQuery transferAccountsDetailQuery, String siteId) {
        Example example = new Example(TransferAccountsDetailDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (transferAccountsDetailQuery.getPeopleId() != null) {
            example.and().andEqualTo("peopleId", transferAccountsDetailQuery.getPeopleId());
        }
        if (transferAccountsDetailQuery.getPhone() != null) {
            example.and().andEqualTo("phone", transferAccountsDetailQuery.getPhone());
        }
        if (transferAccountsDetailQuery.getIdentityBinding() != null) {
            example.and().andEqualTo("identityBinding", transferAccountsDetailQuery.getIdentityBinding());
        }
        if (transferAccountsDetailQuery.getBatchId() != null) {
            example.and().andEqualTo("batchId", transferAccountsDetailQuery.getBatchId());
        }
        if (transferAccountsDetailQuery.getThirdPartyInteriorDetailId() != null) {
            example.and().andEqualTo("thirdPartyInteriorDetailId", transferAccountsDetailQuery.getThirdPartyInteriorDetailId());
        }
        if (transferAccountsDetailQuery.getIsDispose() != null) {
            example.and().andEqualTo("isDispose", transferAccountsDetailQuery.getIsDispose());
        }
        if (StrKit.isNotEmpty(transferAccountsDetailQuery.getName())) {
            example.and()
                    .andLike("name", "%" + transferAccountsDetailQuery.getName() + "%")
                    .orLike("idCard", "%" + transferAccountsDetailQuery.getName() + "%")
                    .orLike("phone", "%" + transferAccountsDetailQuery.getName() + "%");
        }
        // 排序
        ExampleKit.setExampleOrder(example,transferAccountsDetailQuery.getOrders());
        return example;
    }
}




